# coding=utf-8
import re
from decimal import DecimalException, Decimal

from ajax_select.fields import AutoCompleteSelectField
from django import forms
from django.contrib.auth.models import Permission
from django.core.exceptions import ValidationError
from django.utils.translation import ugettext_lazy as _

from core.widget import PhoneWidget, MoneyWidget, CPFWidget, CNPJWidget
from core.models import Company, User, Address, Contact, NaturalPerson, Package, Contract, Group
from gym.models import Activity


class CompanyForm(forms.ModelForm):
    fields_ignore_validation = ['address', 'contact', 'user']
    cnpj = forms.CharField(max_length=18, widget=CNPJWidget(), required=False)

    class Meta:
        model = Company

    def full_clean(self):
        super(CompanyForm, self).full_clean()

        if not self.is_bound:
            return

        for field_to_ignore in self.fields_ignore_validation:
            if field_to_ignore in self._errors:
                del self._errors[field_to_ignore]

        user_instance = User.objects.get(pk=self.data['user']) if 'user' in self.data and self.data['user'] else None
        address_instance = Address.objects.get(pk=self.data['address']) if 'address' in self.data and self.data[
            'address'] else None
        contact_instance = Contact.objects.get(pk=self.data['contact']) if 'contact' in self.data and self.data[
            'contact'] else None

        user_form = UserForm(data=self.data, instance=user_instance)
        address_form = AddressForm(data=self.data, instance=address_instance)
        contact_form = ContactForm(data=self.data, instance=contact_instance)

        check_form = lambda form, errors: errors.update(form._errors) if not form.is_valid() else False

        check_form(user_form, self._errors)
        check_form(address_form, self._errors)
        check_form(contact_form, self._errors)

        cleaned_data = self.cleaned_data
        cleaned_data.update(user_form.cleaned_data)
        cleaned_data.update(address_form.cleaned_data)
        cleaned_data.update(contact_form.cleaned_data)

        return cleaned_data

    def save(self, force_insert=False, force_update=False, commit=True):
        user_instance = User.objects.get(pk=self.data['user']) if 'user' in self.data else None
        address_instance = Address.objects.get(pk=self.data['address']) if 'address' in self.data else None
        contact_instance = Contact.objects.get(pk=self.data['contact']) if 'contact' in self.data else None

        oneToOnes = ['city', 'contract']
        for oneToOne in oneToOnes:
            if oneToOne in self.cleaned_data and self.cleaned_data[oneToOne]:
                self.cleaned_data[oneToOne] = self.cleaned_data[oneToOne].id

        company = super(CompanyForm, self).save(commit=False)
        user = UserForm(data=self.data, instance=user_instance).save()
        contact = ContactForm(data=self.data, instance=contact_instance).save()
        address = AddressForm(data=self.data, instance=address_instance).save()

        company.user = user
        company.address = address
        company.contact = contact

        if commit:
            company.save()
        return company


class NaturalPersonForm(forms.ModelForm):
    current_user = None
    fields_ignore_validation = ['address', 'user', 'contact']
    cpf = forms.CharField(max_length=14, widget=CPFWidget(), required=False)

    class Meta:
        model = NaturalPerson

    def full_clean(self):
        super(NaturalPersonForm, self).full_clean()

        if not self.is_bound:
            return

        for field_to_ignore in self.fields_ignore_validation:
            if field_to_ignore in self._errors:
                del self._errors[field_to_ignore]

        user_instance = User.objects.get(pk=self.data['user']) if 'user' in self.data and self.data['user'] else None
        address_instance = Address.objects.get(pk=self.data['address']) if 'address' in self.data and self.data[
            'address'] else None
        contact_instance = Contact.objects.get(pk=self.data['contact']) if 'contact' in self.data and self.data[
            'contact'] else None

        user_form = UserForm(data=self.data, instance=user_instance)
        address_form = AddressForm(data=self.data, instance=address_instance)
        contact_form = ContactForm(data=self.data, instance=contact_instance)

        check_form = lambda form, errors: errors.update(form._errors) if not form.is_valid() else False

        check_form(user_form, self._errors)
        check_form(address_form, self._errors)
        check_form(contact_form, self._errors)

        cleaned_data = self.cleaned_data
        cleaned_data.update(user_form.cleaned_data)
        cleaned_data.update(address_form.cleaned_data)
        cleaned_data.update(contact_form.cleaned_data)

        return cleaned_data

    def save(self, force_insert=False, force_update=False, commit=True):
        user_instance = User.objects.get(pk=self.data['user']) if 'user' in self.data else None
        address_instance = Address.objects.get(pk=self.data['address']) if 'address' in self.data else None
        contact_instance = Contact.objects.get(pk=self.data['contact']) if 'contact' in self.data else None

        oneToOnes = ['city', 'contract']
        for oneToOne in oneToOnes:
            if oneToOne in self.cleaned_data and self.cleaned_data[oneToOne]:
                self.cleaned_data[oneToOne] = self.cleaned_data[oneToOne].id

        person = super(NaturalPersonForm, self).save(commit=False)
        user = UserForm(data=self.data, instance=user_instance, user=self.current_user).save()
        contact = ContactForm(data=self.data, instance=contact_instance).save()
        address = AddressForm(data=self.data, instance=address_instance).save()

        person.user = user
        person.address = address
        person.contact = contact

        if commit:
            person.save()
        return person

    def __init__(self, *args, **kwargs):
        current_user = kwargs.pop('current_user', None)
        super(NaturalPersonForm, self).__init__(*args, **kwargs)
        self.fields.keyOrder = ['name', 'cpf', 'photo', 'birth_date', 'civil_state', 'blood_group', 'rh_factor', 'sex',
                                'user', 'address', 'contact']
        self.current_user = current_user


class AddressForm(forms.ModelForm):
    city = AutoCompleteSelectField('city', required=True, plugin_options={'autoFocus': True, 'minLength': 2})

    class Meta:
        model = Address

    def __init__(self, *args, **kwargs):
        super(AddressForm, self).__init__(*args, **kwargs)
        self.fields.keyOrder = ['street', 'neighbor', 'postal_code', 'number', 'complement', 'city']


class UserForm(forms.ModelForm):
    password = forms.CharField(label=_('Password'), widget=forms.PasswordInput)
    password2 = forms.CharField(label=_('Password Confirmation'), widget=forms.PasswordInput)
    contract_value = None

    class Meta:
        model = User
        exclude = ('last_login', 'is_email_verified', 'date_joined')

    def clean_password2(self):
        # Check that the two password entries match
        password1 = self.cleaned_data.get("password")
        password2 = self.cleaned_data.get("password2")
        if password1 and password2 and password1 != password2:
            raise forms.ValidationError(_("The passwords don't match"))
        return password2

    def save(self, commit=True):
        # Save the provided password in hashed format
        user = super(UserForm, self).save(commit=False)
        user.set_password(self.cleaned_data["password"])
        if self.contract_value:
            user.contract = self.contract_value
        if commit:
            user.save()
        return user

    def __init__(self, *args, **kwargs):
        user = kwargs.pop('user', None)
        super(UserForm, self).__init__(*args, **kwargs)
        self.fields.keyOrder = ['is_superuser', 'is_active', 'is_staff', 'email', 'password', 'password2', 'contract',
                                'groups', 'user_permissions']
        if user:
            if user.contract:
                self.contract_value = user.contract
                del self.fields['contract']
                del self.fields['is_staff']

            if user.contract:
                self.contract_value = user.contract
                self.fields['user_permissions'].queryset = user.contract.package.permissions
                self.fields['groups'].queryset = Group.objects.filter(contract=user.contract)
            else:
                self.fields['user_permissions'].queryset = Permission.objects.all()
                self.fields['groups'].queryset = Group.objects.all()


class ContactForm(forms.ModelForm):
    class Meta:
        model = Contact

    residential_phone = forms.CharField(max_length=14, widget=PhoneWidget(), required=False,
                                        label=_('Residential Phone'))
    cell_phone = forms.CharField(max_length=14, widget=PhoneWidget(), required=False, label=_('Cellphone'))
    work_phone = forms.CharField(max_length=14, widget=PhoneWidget(), required=False, label=_('Work Phone'))

    def __init__(self, *args, **kwargs):
        super(ContactForm, self).__init__(*args, **kwargs)
        self.fields.keyOrder = ['cell_phone', 'residential_phone', 'work_phone']


class MoneyField(forms.DecimalField):
    def to_python(self, value):
        try:
            return super(MoneyField, self).to_python(value)
        except ValidationError:
            value = re.sub('[R$\s.]', '', value)
            value = re.sub('[,]', '.', value)
            try:
                value = Decimal(value)
            except DecimalException:
                raise ValidationError(self.error_messages['invalid'])
            return value
        return None

    def __init__(self):
        super(MoneyField, self).__init__(widget=MoneyWidget())


class PackageForm(forms.ModelForm):
    price = MoneyField()

    class Meta:
        model = Package


class ActivityForm(forms.ModelForm):
    price = MoneyField()

    class Meta:
        model = Activity

    def __init__(self, *args, **kwargs):
        super(ActivityForm, self).__init__(*args, **kwargs)
        self.fields.keyOrder = ['name', 'price']


class ContractForm(forms.ModelForm):
    class Meta:
        model = Contract

    package = AutoCompleteSelectField('package', required=True, plugin_options={'autoFocus': True, 'minLength': 2})


#################
class ListForm():
    list_display = []
    objects = []
    model = None

    def __init__(self, *args, **kwargs):
        self.objects = kwargs.pop('objects', None)
        #self.list_display = kwargs.pop('list_display', None)
        #self.model = kwargs.pop('model', None)


class ActivityListForm(ListForm):
    list_display = ['name', 'price']
    model = Activity.__name__